home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-10-20 | 9.0 KB | 354 lines | [TEXT/MPS ] |
- /*
- File: DcmdShell.c
-
- Contains: This is the DcmdShell dcmd. This shell gives you a good start
- for a new Dcmd with a command line parser.
-
- Version: 1.0
-
- Written by: Jim Luther
-
- Copyright: © 1998-1999 by Apple Computer, Inc., All Rights Reserved.
-
- File Ownership:
-
- DRI: Jim Luther
-
- Other Contact: Dave Lyons or Jim Murphy
-
- Technology: MacsBug Dcmds
-
- Writers:
-
- (JM3) Jim Murphy
- (JL) Jim Luther
-
- Change History (most recent first):
-
- <2> 10/12/99 JM3 Added some unsigneds to make CodeWarrior builds happy.
- <1> 10/11/99 JL first checked in
- <0> 10/15/98 JL New today.
-
- To do:
-
- */
-
- //*******************************************************************************************************
-
- #include <MacTypes.h>
- #include <StringCompare.h>
-
- #include "dcmd.h"
- #include "put.h"
-
- //*******************************************************************************************************
- //
- // Constants and defines
- //
-
- // The Dcmd's version number
- #define kDcmdVersionNumber \
- { \
- 0x01, /* 1st part of version number in BCD */ \
- 0x00, /* 2nd & 3rd part of version number share a byte */ \
- betaStage, /* stage code: developStage, alphaStage, betaStage, finalStage */ \
- 0x01 /* revision level of non-released version */ \
- }
-
- // The Dcmd's usage string (displayed by "DCMD DcmdShell" or by "? dcmds" or "help dcmds")
- #define kDcmdUsageStr "\p[expression1 [expression2]] [-X] [-Y value] [-Z ON|OFF]"
-
- // the Dcmd's error prefix string
- #define kDcmdErrPrefixStr "\pDcmdShell - Error: "
-
- // The maximum number of numeric expressions to parse from command line
- enum
- {
- kMaxExpressions = 2 // maximum number of expressions to parse from command line
- };
-
- // StringsEqual - a case-insensitive, diacritical-sensitive string compare that's safe to
- // call at interrupt time that the parser uses for comparing parameter strings
- #define StringsEqual(p1, p2) EqualString(p1, p2, false, true)
-
-
- //*******************************************************************************************************
- //
- // Globals
- //
-
- static const unsigned char gUsageStr[] = kDcmdUsageStr;
-
- static const unsigned char gDcmdErrPrefixStr[] = kDcmdErrPrefixStr;
-
- static NumVersionVariant gDcmdVersionNumber = kDcmdVersionNumber;
-
- //*******************************************************************************************************
- //
- // Prototypes
- //
-
- Boolean ParseParameters(UInt32 *expressionCount, UInt32 *expressions,
- Boolean *optionX, UInt32 *optionY, Boolean *optionZ);
-
- pascal void DcmdCore(dcmdBlockPtr paramPtr);
-
- pascal void CommandEntry(dcmdBlockPtr paramPtr);
-
- //*******************************************************************************************************
- //
- // ParseParameters
- //
- // Scan through the entire command line to validate all the parameters.
- // Returns true if the line parsed, false if it didn’t.
- //
- // Command line syntax:
- // DcmdShell [expression1 [expression2]] [-X] [-Y value] [-Z ON|OFF]
- //
- Boolean ParseParameters(UInt32 *expressionCount, UInt32 *expressions,
- Boolean *optionX, UInt32 *optionY, Boolean *optionZ)
- {
- Boolean parseOK;
- short position;
- short delimiter;
- Str255 parameterStr;
- Boolean okExpression;
- long value;
- UInt32 i;
-
- // Default settings for parameters
- *expressionCount = 0;
- for ( i = 0; i < kMaxExpressions; ++i )
- {
- expressions[i] = 0;
- }
- *optionX = false;
- *optionY = 0;
- *optionZ = false;
-
- // The parser first looks for string parameters.
- // If the current parameter doesn't match any strings, then it is evaluated as an expression.
- // By getting string parameters first, we can ensure that an dash option like "-A" is not seen as the value #-10.
- parseOK = true;
- do
- {
- position = dcmdGetPosition(); // Save current position in case we need to back up and try again as an expression
- delimiter = dcmdGetNextParameter(parameterStr); // Get the next parameter (if any) and the delimiter
- if ( parameterStr[0] != 0 )
- {
- // Is it a '-' or a string parameter?
- if ( StringsEqual(parameterStr, "\p-X") )
- {
- // -X has no additional parameters
-
- // change the setting to the non-default value
- *optionX = !*optionX;
- }
- else if ( StringsEqual(parameterStr, "\p-Y") )
- {
- // -Y has a expression parameter
-
- delimiter = dcmdGetNextExpression(&value, &okExpression);
- if (okExpression)
- {
- // return the expression passed for the -Y option
- *optionY = value;
- }
- else
- {
- // The expression was bad
- PutPStr(gDcmdErrPrefixStr);
- PutPStr("\p-Y expression was invalid");
- PutLine();
- parseOK = false;
- }
- }
- else if ( StringsEqual(parameterStr, "\p-Z") )
- {
- // -Z has a string parameter
-
- delimiter = dcmdGetNextParameter(parameterStr);
- if ( StringsEqual(parameterStr, "\pON") )
- {
- *optionZ = true;
- }
- else if ( StringsEqual(parameterStr, "\pOFF") )
- {
- *optionZ = false;
- }
- else
- {
- // It wasn't a parameter we expected
- PutPStr(gDcmdErrPrefixStr);
- PutPStr("\p-Z parameter was invalid");
- PutLine();
- parseOK = false;
- }
- }
- else
- {
- // Restore position if parameter not handled as string
- dcmdSetPosition(position);
-
- // and then try it as an expression
- delimiter = dcmdGetNextExpression(&value, &okExpression);
- if (okExpression)
- {
- // Return the expression if we haven't reached the maximum
- if ( *expressionCount < kMaxExpressions )
- {
- expressions[*expressionCount] = value;
- ++(*expressionCount);
- }
- else
- {
- // Too many expression parameters
- PutPStr(gDcmdErrPrefixStr);
- PutPStr("\pToo many expression parameters");
- PutLine();
- parseOK = false;
- }
- }
- else
- {
- // Bad comand line
- PutPStr(gDcmdErrPrefixStr);
- PutPStr("\pParameter could not be parsed");
- PutLine();
- parseOK = false;
- }
- }
- }
-
- } while ( (delimiter != 0x0d) && parseOK ); // look until the end of the line or until there's a problem
-
- if ( !parseOK )
- {
- // Burn the rest of the command line so MacsBug won't complain
- // that "Command did not use all parameters"
- do
- {
- delimiter = dcmdGetNextParameter(parameterStr);
- } while ( delimiter != 0x0d );
- }
-
- return ( parseOK );
-
- } // ParseParameters
-
-
- //*******************************************************************************************************
- //
- // DcmdCore
- //
- // The main "do it" code
- //
- pascal void DcmdCore(dcmdBlockPtr paramPtr)
- {
- // This sample doesn't use the dcmdBlockPtr parameter, but go look at all the cool stuff
- // your Dcmd is passed (dcmd.h).
- //
- // In particular, if your Dcmd is going to do any time-comsuming tasks (like displaying large
- // amounts of information) and you want the user to be able to abort, your Dcmd should watch
- // the "aborted" field and exit if it changes to TRUE.
- #pragma unused(paramPtr)
-
- UInt32 expressionCount;
- UInt32 expressions[kMaxExpressions];
- Boolean optionX;
- UInt32 optionY;
- Boolean optionZ;
- UInt32 i;
-
- // Get command line parameters (if any)
- if ( ParseParameters(&expressionCount, expressions, &optionX, &optionY, &optionZ) == true )
- {
- PutPStr("\pDcmdShell:");
- PutLine();
-
- // Display the parsed parameters
-
- // Display the expression parameters (if any)
- if ( expressionCount == 0 )
- {
- PutPStr("\pNo expression parameters");
- PutLine();
- }
- else
- {
- for ( i = 0; i < expressionCount; ++i )
- {
- PutPStr("\pExpression ");
- PutUDec(i + 1);
- PutPStr("\p = $");
- PutUHexZ(expressions[i], 8);
- PutLine();
- }
- }
-
- // Display the string parameters
- PutPStr("\pOptionX = ");
- PutPStr(optionX ? "\pTRUE" : "\pFALSE");
- PutLine();
-
- PutPStr("\pOptionY = $");
- PutUHexZ(optionY, 8);
- PutLine();
-
- PutPStr("\pOptionZ = ");
- PutPStr(optionZ ? "\pON" : "\pOFF");
- PutLine();
- }
- } // DcmdCore
-
- //*******************************************************************************************************
- //
- // CommandEntry
- //
- // The main entry point for this dcmd
- //
- pascal void CommandEntry(dcmdBlockPtr paramPtr)
- {
- switch ( paramPtr->request )
- {
- case dcmdInit:
- // Initialize the Dcmd
- // (called when MacsBug is loaded)
- break;
-
- case dcmdDoIt:
- // Normal Dcmd execution
- // (called when MacsBug wants us to do our job)
- dcmdSwapWorlds();
- DcmdCore(paramPtr);
- dcmdSwapWorlds();
- break;
-
- case dcmdHelp:
- // Display help for Dcmd
- dcmdDrawLine("\pA sample dcmd shell");
- break;
-
- case dcmdSecondaryInit:
- // Second time to init after all System patches have been loaded
- // (called just before extensions are executed)
- break;
-
- case dcmdShutdown:
- // Dcmd should remove or disable its patches (if any).
- break;
-
- case dcmdGetInfo:
- // Return Dcmd version and usage string
- dcmdFillVersion(paramPtr, gDcmdVersionNumber.whole);
- dcmdFillString(paramPtr, usageStr, gUsageStr);
- break;
-
- default:
- // Version 3 and later Dcmds must quietly ignore unrecognized requests
- break;
- }
- } // CommandEntry
-
- //*******************************************************************************************************
-